package com.xiashitech.agent.instrumentation.spring.controller.apicapture.utils;

import com.xiashitech.agent.config.StartConfig;
import com.xiashitech.agent.constants.ErrorCode;
import com.xiashitech.agent.grpc.XsApiInfoClient;
import com.xiashitech.agent.instrumentation.log.XSLevel;
import com.xiashitech.agent.utils.XiashiGrpcUtil;
import com.xiashitech.agent.utils.HttpUtil;
import com.xiashitech.agent.utils.JsonUtil;
import com.xiashitech.interfaces.agent.dto.AgentConfigDTO;
import com.xiashitech.interfaces.agent.dto.api.ApiRequest;
import com.xiashitech.interfaces.agent.dto.api.ApiResponse;
import com.xiashitech.interfaces.agent.dto.api.DesenseParam;
import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig;

import java.util.HashSet;
import java.util.Set;
import java.util.logging.Logger;

import static java.util.logging.Level.*;
import static java.util.logging.Level.WARNING;

public class ApiSyncUtil {
    private static final Logger logger = Logger.getLogger(ApiSyncUtil.class.getName());
    private static Set<DesenseParam> syncDesenseParamCache = new HashSet();
    public static void syncApiDesense(DesenseParam desenseParam) {
        if(syncDesenseParamCache.contains(desenseParam)) {
            return;
        }
        new Thread(() -> {
            try {
                if(desenseParam == null || desenseParam.getApiName() == null || desenseParam.getApiName().isEmpty()) {
                    return;
                }
                if(XiashiGrpcUtil.useGrpc()) {
                    XsApiInfoClient.getClient().grpcPushDesenseServer(desenseParam);
                } else {
                    String response = HttpUtil.doPost(AgentConfigDTO.getConfig().getDesenseservice(), JsonUtil.convertObjectToString(ApiRequest.builder().desenseParam(desenseParam).build()), "application/json;charset=UTF-8");
                    if (response != null && !response.isEmpty() && JsonUtil.isJson(response)) {
                        ApiResponse apiResponse = JsonUtil.convertStringToObject(response, ApiResponse.class);
                        if (apiResponse.getCode() != null && apiResponse.getCode().equals(ErrorCode.RESULT_1001.getCode())) {
                            cacheDesense(desenseParam);
                            if (logger.isLoggable(FINE)) {
                                logger.log(FINE, "The change to desenseParam({0}) of the api({1}) has been transferred to openmetadata", new Object[]{desenseParam.getDesenseParam(), desenseParam.getApiName()});
                            } else {
                                if (InstrumentationConfig.get().getBoolean("xs.debug", false)) {
                                    logger.log(XSLevel.DEBUG, "The change to desenseParam({0}) of the api({1}) has been transferred to openmetadata", new Object[]{desenseParam.getDesenseParam(), desenseParam.getApiName()});
                                } else {
                                    logger.log(INFO, "The change to desenseParam({0}) of the api({1}) has been transferred to openmetadata", new Object[]{desenseParam.getDesenseParam(), desenseParam.getApiName()});
                                }
                            }
                        } else {
                            if (InstrumentationConfig.get().getBoolean("xs.debug", false)) {
                                logger.log(XSLevel.DEBUG, "The change to desenseParam({0}) of the api({1}) has not been transferred to openmetadata", new Object[]{desenseParam.getDesenseParam(), desenseParam.getApiName()});
                            } else {
                                logger.log(WARNING, "The change to desenseParam({0}) of the api({1}) has not been transferred to openmetadata", new Object[]{desenseParam.getDesenseParam(), desenseParam.getApiName()});
                            }
                        }
                    } else {
                        if (InstrumentationConfig.get().getBoolean("xs.debug", false)) {
                            logger.log(XSLevel.DEBUG, "The change to desenseParam({0}) of the api({1}) has not been transferred to openmetadata", new Object[]{desenseParam.getDesenseParam(), desenseParam.getApiName()});
                        } else {
                            logger.log(WARNING, "The change to desenseParam({0}) of the api({1}) has not been transferred to openmetadata", new Object[]{desenseParam.getDesenseParam(), desenseParam.getApiName()});
                        }
                    }
                }
            } catch (Throwable e) {
                logger.log(XSLevel.DEBUG, "The Agent fails to transfer the changes to desenseParam of the api to Agentservice.");
                StartConfig.throwableStackPrinter(e);
            }
        }).start();
    }
    public static void cacheDesense(DesenseParam desenseParam) {
        synchronized (syncDesenseParamCache) {
            syncDesenseParamCache.add(desenseParam);
        }
    }
}
